#include <stdlib.h>
#include <Adafruit_GFX.h>    // Core graphics library
#include <Adafruit_TFTLCD.h> // Hardware-specific library
#include <SPI.h>
#include <SD.h>

#define LCD_CS A3 // Chip Select goes to Analog 3
#define LCD_CD A2 // Command/Data goes to Analog 2
#define LCD_WR A1 // LCD Write goes to Analog 1
#define LCD_RD A0 // LCD Read goes to Analog 0
#define LCD_RESET A4 // Can alternately just connect to Arduino's reset pin
#define BLACK   0x0000
#define BLUE    0x001F
#define RED     0xF800
#define GREEN   0x07E0
#define CYAN    0x07FF
#define MAGENTA 0xF81F
#define YELLOW  0xFFE0
#define WHITE   0xFFFF

#include <MCUFRIEND_kbv.h>
MCUFRIEND_kbv tft;

#define PROXY 1 //0 普通,1 穿透

void servlets(char* method, char* url, char* version_);
void wifi_respond(char client_char, String respond_);
void sendplainfile(char* url);

void setup() {
    Serial.begin(9600);
    
    tft.reset();
    uint16_t identifier = tft.readID();if(identifier==0x0101)identifier=0x9341;else identifier=0x7793;
    tft.begin(identifier);
    tft.fillScreen(BLACK);
    tft.setCursor(0, 0);
    tft.setTextColor(WHITE);tft.setTextSize(2);
    if (!SD.begin())
    {
        Serial.println("Insert SD!");
        while(!SD.begin());
    }
    echoln("server at: 192.168.43.196");
    echo("listening to 80\n");

    wifi("ATE0\r\n");
    wifi("AT+CWMODE=3\r\n"); //热点&主机模式
    wifi("AT+CIPMUX=1\r\n");  //设置多链接
    wifi("AT+CIPSERVER=1,80\r\n");//建立服务器，0关闭
    #if PROXY
        wifi("AT+CIPSTART=0,\"TCP\",\"ysuxzh.com\",8001\r\n");//192.168.43.236
        echo("proxy mode\n");
    #endif
}

const char* baserespond = "HTTP/1.1 200 OK\nContent-Type: text/html\n\n";

void wifi(char* str){
    Serial.print(str);
    delay(500);
}

void wifi(const char* str){
    Serial.print(str);
    delay(500);
}

void echo(char* str){
    tft.print(str);
}

void echo(const char* str){
    tft.print(str);
}

void echoln(char* str){
    tft.println(str);
}

void echoln(const char* str){
    tft.println(str);
}

//服务器请求参数
char client_char;
char* c_lines;
char* method;
char* url;
char* version_;
String lines;

void loop() {
    servermode();
}

void servermode(){
    lines = "";
    char c;
    while (Serial.available() > 0){
        c = Serial.read();
        lines += c;
        if(c == '\n' and lines != "\n"){
            char* p = (char*)lines.c_str();
            int index = lines.indexOf("+IPD");
            if(index > -1){//判断第一行，请求行处理
                client_char = lines[index + 5];
                index = lines.indexOf(":");
                char* t1 = p + index + 1;
                method = strtok(t1, " ");
                url = strtok(NULL, " ");
                version_ = strtok(NULL, " ");
                String p = p + index + 1;
                servlets(client_char, method, url, version_);
                lines = "";
             }
        }
        delay(2);
    }
}

void servlets(char client_char, char* method, char* url, char* version_){
    echo(method);echo(" ");
    int l = strlen(url);
    if(url[l - 1] == '/'){
        url[l] = '0';
        url[l + 1] = '\0';
    }
    echoln(url);
    #ifdef PROXY
//         wifi_respond(client_char, "<h1>hello world!</h1>\4");
        sendplainfile(url);
//        wifi_respond(client_char, "\4");
    #else
        sendplainfile(url);
        close_respond(client_char);
    #endif
}

void sendplainfile(char* url){
    #ifndef PROXY
        wifi_respond(client_char, baserespond);
    #endif //代理模式，在服务器端发送baserespond.
    File file = SD.open(url);//这句话会导致有很大概率不能发送信息。猜测是因为内存不足。因此进行内存优化。
    if (file)
    {
        String text;int len = 0;char c;
        while (file.available())
        {
             c = file.read();
             text += c;
             len++;
             if(len >= 100){//80稳定，100就炸了。
                 wifi_respond(client_char, text);
                 len = 0;
                 text = "";
             }
        }
        wifi_respond(client_char,text);
        echoln(" ok");
        file.close();
    }
    else
    {
        wifi_respond(client_char, url);
        wifi_respond(client_char, "404");
        echoln(" 404");
    }
}
    
void wifi_respond(char client_char, String respond_){
    //将信息发送给指定客户端。
    char len[5];
    String cc = "AT+CIPSEND=";cc += client_char;cc += ",";cc += itoa(respond_.length(), len, 10);cc += "\r\n";
    wifi((char*)cc.c_str());
    delay(600);//8266的接受延迟。500在某些情况下不行。
    wifi((char*)respond_.c_str());
    delay(1000);//不知名的延迟。
    return;
}

void close_respond(char client){
    String cc = "AT+CIPCLOSE=";cc += client_char;cc += "\r\n";
    wifi((char*)cc.c_str());
    return;
}
